home *** CD-ROM | disk | FTP | other *** search
/ Sounds Terrific 2 / Sounds Terrific II (1996)(Weird Science)(Disc 1 of 2)[Amiga-PC].iso / archives / amiga / tracker_4_31.lzh / tracker / main.c < prev    next >
C/C++ Source or Header  |  1995-05-15  |  17KB  |  648 lines

  1. /* main.c 
  2.     vi:ts=3 sw=3:
  3.  */
  4.  
  5. /* plays sound/noisetracker files on Sparc, silicon graphics.
  6.  * Authors  : Liam Corner - zenith@dcs.warwick.ac.uk
  7.  *            Marc Espie - espie@ens.fr
  8.  *            Steve Haehnichen - shaehnic@ucsd.edu
  9.  *            Andrew Leahy - alf@st.nepean.uws.edu.au
  10.  *
  11.  * Usage    : tracker <filename> 
  12.  *  this version plays compressed files as well.
  13.  */
  14.  
  15. /* $Id: main.c,v 4.25 1995/05/15 12:20:00 espie Exp espie $
  16.  * $Log: main.c,v $
  17.  * Revision 4.25  1995/05/15  12:20:00  espie
  18.  * *** empty log message ***
  19.  *
  20.  * Revision 4.24  1995/04/22  17:50:20  espie
  21.  * *** empty log message ***
  22.  *
  23.  * Revision 4.23  1995/03/17  00:32:22  espie
  24.  * TERM from #ifdef to pref option.
  25.  *
  26.  * Revision 4.22  1995/03/11  23:06:33  espie
  27.  * version changed.
  28.  *
  29.  * Revision 4.21  1995/03/06  22:35:38  espie
  30.  * Color can be default.
  31.  *
  32.  * Revision 4.20  1995/03/01  15:24:51  espie
  33.  * options -half/-double.
  34.  *
  35.  * Revision 4.19  1995/02/24  15:36:39  espie
  36.  * Case forgotten: if file does not open, song is not set.
  37.  *
  38.  * Revision 4.18  1995/02/21  21:13:16  espie
  39.  * Cleaned up source. Moved minor pieces of code around.
  40.  *
  41.  * Revision 4.17  1995/02/21  17:54:32  espie
  42.  * Internal problem: buggy RCS. Fixed logs.
  43.  *
  44.  * Revision 4.13  1995/02/15  14:30:09  espie
  45.  * optarg being NULL not checked -> segmentation.
  46.  *
  47.  * Revision 4.11  1995/02/14  04:02:28  espie
  48.  * Added version number.
  49.  *
  50.  * Revision 4.9  1995/02/01  20:41:45  espie
  51.  * Added color.
  52.  *
  53.  * Revision 4.8  1995/02/01  16:39:04  espie
  54.  * Loading formats thru rewind.
  55.  *
  56.  * Revision 4.5  1994/08/23  18:19:46  espie
  57.  * Added speed mode option.
  58.  * Added looping option.
  59.  * Nice OPT_CUT/OPT_ADD.
  60.  * Slight input/output changes.
  61.  * No more call to create_notes_table().
  62.  * Some notice to status.
  63.  * Use new pref scheme.
  64.  * Use info facility instead of printf for usage message.
  65.  * Options changes.
  66.  * Changed extended file semantics.
  67.  * Amiga support.
  68.  * Fixed upo previous song bug.
  69.  * Added bg/fg test.
  70.  * Added loads of new options.
  71.  * Added finetune.
  72.  *
  73.  * Revision 2.20  1992/11/17  17:06:25  espie
  74.  * Added PREVIOUS_SONG handling ???
  75.  * Use streamio for new interface (obsolescent signal handlers), and
  76.  * related changes.
  77.  * Cleaned up path reader, and better signal handling.
  78.  * Support for open_file.
  79.  * Added imask.
  80.  * Use transparent decompression/path lookup through open_file/close_file.
  81.  * Added setup_audio().
  82.  * Added some frequency/oversample/stereo change on the fly.
  83.  * Necessitates rightful closing/reopening of audio.
  84.  * Added compression methods. Changed getopt.
  85.  * Separated mix/stereo stuff.
  86.  * Added transpose feature.
  87.  * Added possibility to get back to MONO for the sgi.
  88.  * Added stereo capabilities to the indigo version.
  89.  * Added recovery and reread for automatic recognition
  90.  * of old/new tracker files.
  91.  * Added two level of fault tolerancy.
  92.  * Added more rational options.
  93.  * Moved almost everything to audio and automaton.
  94.  * Structured part of the code, especially replay ``automaton''
  95.  * and setting up of effects.
  96.  *
  97.  * Revision 1.26  1991/11/17  17:09:53  espie
  98.  * Added missing prototypes.
  99.  * Some more info while loading files.
  100.  * Added FAULT env variable, FAULT resistant playing,
  101.  * for playing modules which are not quite correct.
  102.  * Serious bug: dochangespeed was not reset all the time.
  103.  * Check all these parameters, they MUST be reset for
  104.  * each new song.
  105.  * Fixed a stupid bug: when env variable LOOPING was
  106.  * undefined, we got a segv on strcmp.
  107.  * Now we just test for its existence, since this is
  108.  * about all we want...
  109.  * Bug correction: when doing arpeggio, there might not
  110.  * be a new note, so we have to save the old note value
  111.  * and do the arppeggio on that note.
  112.  * Completely added control with OVERSAMPLE and FREQUENCY.
  113.  * Added control flow.
  114.  * Added pipe decompression, so that now you can do
  115.  * str32 file.Z directly.
  116.  * stdin may go away.
  117.  * Added arpeggio.
  118.  * Added vibslide and portaslide.
  119.  * Added speed command.
  120.  * Added signal control.
  121.  * Error checking: there shouldn't be that many
  122.  * segv signals any more.
  123.  * Moved every command to commands.c.
  124.  * Added some debug code for showing the full
  125.  * sequence for a file.
  126.  * Corrected the bug in volume slide: there is
  127.  * no default value, i.e., if it is 0, it is 0,
  128.  * as stupid as it may seem.
  129.  * Added vibrato.
  130.  * Added fastskip/corrected skip.
  131.  * Modified control flow of the player till
  132.  * it looks like something reasonable (i.e.,
  133.  * the structure is more natural and reflects
  134.  * the way stuff is played actually...)
  135.  * Do not restart the sound when we change instruments
  136.  * on the fly. A bit strange, but it works that way.
  137.  * Modified main to use new data structures.
  138.  * The sound player is MUCH cleaner, it uses now
  139.  * a 3-state automaton for each voice.
  140.  * Corrected ruckus with data type of sample.
  141.  */
  142.      
  143.  
  144. #include "defs.h"
  145.  
  146. extern char *VERSION;
  147.  
  148. #include <signal.h>
  149. #include <ctype.h>
  150. #ifdef VOLUME_CONTROL
  151. #ifdef __hpux
  152. #define true /* kludge to avoid typedef of boolean (name clash with macro) */
  153. #include <audio/Alib.h>
  154. #undef true
  155. AGainDB    volume = -20;
  156. char use_speaker = 0;
  157. #endif
  158. #endif
  159.  
  160.      
  161. #include "song.h"
  162. #include "extern.h"
  163. #include "options.h"
  164.  
  165. #include "getoption.h"
  166. #include "tags.h"
  167. #include "prefs.h"
  168.      
  169. ID("$Id: main.c,v 4.25 1995/05/15 12:20:00 espie Exp espie $")
  170.  
  171.  
  172. LOCAL void print_usage()
  173.    {
  174.    GENERIC handle;
  175.    handle = begin_info("Usage");
  176.    infos(handle, "This is tracker ");
  177.     info(handle, VERSION);
  178.     info(handle, "This program is NOT to be redistributed");
  179.     info(handle, "         without the full documentation");
  180.     info(handle, "");
  181.    info(handle, "Usage: tracker [options] filename [...]");
  182.    info(handle, "-help               Display usage information");
  183.    info(handle, "-picky              Do not tolerate any faults (default is to ignore most)");
  184.    info(handle, "-tolerant           Ignore all faults");
  185.    info(handle, "-mono               Select single audio channel output");
  186.    info(handle, "-stereo             Select dual audio channel output");
  187.    info(handle, "-verbose            Show text representation of song");
  188.    info(handle, "-repeats <count>    Number of repeats (0 is forever) (default 1)");
  189.     info(handle, "-loop               Loops the song list (plays again and again)");
  190.    info(handle, "-speed <speed>      Song speed.  Some songs want 60 (default 50)");
  191.    info(handle, "-mix <percent>      Percent of channel mixing. (0 = spatial, 100 = mono)");
  192.    info(handle, "-new -old -both     Select default reading type (default is -both)");
  193.    info(handle, "-frequency <freq>   Set playback frequency in KHz");
  194.    info(handle, "-oversample <times> Set oversampling factor");
  195.    info(handle, "-transpose <n>      Transpose all notes up");
  196.    info(handle, "-scroll             Show what's going on");
  197.    info(handle, "-color              Ansi color scrolling");
  198.    info(handle, "-sync               Try to synch audio output with display");
  199. #ifdef VOLUME_CONTROL
  200.     info(handle, "-speaker                 Output audio to internal speaker");
  201.     info(handle, "-volume <n>         Set volume in dB");
  202. #endif
  203.    info(handle, "");
  204.    info(handle, "RunTime:");
  205.    info(handle, "e,x     exit program");
  206.    info(handle, "n       next song");
  207.    info(handle, "p       restart/previous song");
  208.    info(handle, ">       fast forward");
  209.    info(handle, "<       rewind");
  210.    info(handle, "S       NTSC tempo\t s\tPAL tempo");
  211.    end_info(handle);
  212.    }
  213.  
  214. /* Command-line options. */
  215. LOCAL struct long_option long_options[] =
  216. {
  217.    {"help",                0, 'H', OPT_HELP},
  218.    {"picky",               0, 'P', OPT_PICKY},
  219.    {"tolerant",            0, 'L', OPT_TOLERANT},
  220.    {"new",                 0, 'N', OPT_NEWONLY},
  221.    {"old",                 0, 'O', OPT_OLDONLY},
  222.    {"both",                0, 'B', OPT_BOTH},
  223.    {"mono",                0, 'M', OPT_MONO},
  224.    {"stereo",              0, 'S', OPT_STEREO},
  225.    {"verbose",             0, 'V', OPT_VERBOSE},
  226.    {"frequency",           1, 'f', OPT_FREQUENCY},
  227.    {"oversample",          1, 'o', OPT_OVERSAMPLE},
  228.    {"transpose",           1, 't', OPT_TRANSPOSE},
  229.    {"repeats",             1, 'r', OPT_REPEATS},
  230.    {"speed",               1, 's', OPT_SPEED},
  231.    {"mix",                 1, 'm', OPT_MIX},
  232.    {"start",               1, 'X', OPT_START},
  233.    {"cut",                 1, '-', OPT_CUT},
  234.    {"add",                 1, '+', OPT_ADD},
  235.    {"half",                1, '/', OPT_HALF},
  236.    {"double",              1, '2', OPT_DOUBLE},
  237.    {"scroll",              0, 'v', OPT_SHOW},
  238.     {"color",                    0, 0, OPT_COLOR},    
  239.     {"bw",                        0, 0, OPT_BW},    
  240.     {"xterm",                    0, 0, OPT_XTERM},    
  241.     {"noxterm",                    0, 0, OPT_NOXTERM},    
  242.    {"sync",                0, '=', OPT_SYNC},
  243.     {"loop",                        0, 'l', OPT_LOOP},
  244.     {"speedmode",               1, '?', OPT_SPEEDMODE},
  245. #ifdef VOLUME_CONTROL
  246.     {"speaker",                    0, '#', OPT_SPEAKER},
  247.     {"volume",                    1, 'u', OPT_VOLUME},
  248. #endif
  249.    {0,                     0,  0 , 0}
  250. };
  251.  
  252.  
  253. /* global variable to catch various types of errors and achieve the 
  254.  * desired flow of control
  255.  */
  256. int error;
  257.  
  258. LOCAL unsigned long half_mask = 0;
  259.  
  260. /* v = optvalue(def):
  261.  * obtain a numeric value for an option, with default being def
  262.  */
  263. LOCAL int optvalue(def)
  264. int def;
  265.    {
  266.    int d;
  267.  
  268.    if (optarg && sscanf(optarg, "%d", &d) == 1)
  269.       return d;
  270.    else
  271.       {
  272.       optind--;
  273.       return def;
  274.       }
  275.    }
  276.  
  277. /* some preferences that don't need to be global */
  278.  
  279.  
  280. LOCAL int ask_freq;        /* parameters for setup audio */
  281. LOCAL int oversample;
  282. LOCAL int stereo;
  283.  
  284. LOCAL int start;            /* parameters for st_play */
  285. LOCAL int transpose;
  286.  
  287. LOCAL int loop = FALSE;    /* main automaton looping at end of argv ? */
  288.  
  289.  
  290. LOCAL void parse_options(argc, argv)
  291. int argc;
  292. char *argv[];
  293.    {
  294.    int c;
  295.    
  296.    while ((c = getlongopt(argc, argv, long_options))
  297.       != BAD_OPTION)
  298.       switch(c)
  299.          {
  300.         case OPT_LOOP:
  301.             loop = TRUE;
  302.             break;
  303.         case OPT_CUT:
  304.         case OPT_ADD:
  305.         case OPT_HALF:
  306.             {
  307.             int i;
  308.             unsigned long imask = 0;
  309.       
  310.             for (i = 0; optarg && optarg[i]; i++)
  311.                 {
  312.                 char c = tolower(optarg[i]);
  313.  
  314.                 if (c >= '1' && c <= '9')
  315.                     imask |= 1<< (c-'0');
  316.                 else if (c >= 'a' && c <= 'z')
  317.                     imask |= 1 << (c-'a'+10);
  318.                 }
  319.             switch(c)
  320.                 {
  321.             case OPT_ADD:
  322.                 set_pref_scalar(PREF_IMASK, ~imask);
  323.                 break;
  324.             case OPT_CUT:
  325.                 set_pref_scalar(PREF_IMASK, imask);
  326.                 break;
  327.             case OPT_HALF:
  328.                 half_mask = imask;
  329.                 break;
  330.             case OPT_DOUBLE:
  331.                 half_mask = ~imask;
  332.                 }
  333.             }        
  334.          break;
  335.         case OPT_SPEEDMODE:
  336.             if (optarg)
  337.                 {
  338.                 if (stricmp(optarg, "old") == 0)
  339.                     set_pref_scalar(PREF_SPEEDMODE, OLD_SPEEDMODE);
  340.                 else if (stricmp(optarg, "normal") == 0)
  341.                     set_pref_scalar(PREF_SPEEDMODE, NORMAL_SPEEDMODE);
  342.                 else if (stricmp(optarg, "finefirst") == 0)
  343.                     set_pref_scalar(PREF_SPEEDMODE, FINESPEED_ONLY);
  344.                 else if (stricmp(optarg, "normalfirst") == 0)
  345.                     set_pref_scalar(PREF_SPEEDMODE, SPEED_ONLY);
  346.                 }
  347.             break;
  348.             
  349.       case OPT_OLDONLY:   /* old tracker type */
  350.          set_pref_scalar(PREF_TYPE, OLD);
  351.          break;
  352.       case OPT_NEWONLY:   /* new tracker type */
  353.          set_pref_scalar(PREF_TYPE, NEW);
  354.          break;
  355.       case OPT_SHOW:
  356.          set_pref_scalar(PREF_SHOW, TRUE);
  357.          break;
  358.         case OPT_XTERM:
  359.             set_pref_scalar(PREF_XTERM, TRUE);
  360.             break;
  361.         case OPT_NOXTERM:
  362.             set_pref_scalar(PREF_XTERM, FALSE);
  363.             break;
  364.         case OPT_COLOR:
  365.             set_pref_scalar(PREF_COLOR, TRUE);
  366.             break;
  367.         case OPT_BW:
  368.             set_pref_scalar(PREF_COLOR, FALSE);
  369.             break;
  370.       case OPT_SYNC:
  371.          set_pref_scalar(PREF_SYNC, TRUE);
  372.          break;
  373.       case OPT_BOTH:   /* both tracker types */
  374.          set_pref_scalar(PREF_TYPE, BOTH);
  375.          break;
  376.       case OPT_REPEATS:   /* number of repeats */
  377.          set_pref_scalar(PREF_REPEATS, optvalue(0));
  378.          break;
  379.       case OPT_SPEED:  
  380.          set_pref_scalar(PREF_SPEED, optvalue(50));
  381.          break;
  382.       case OPT_MONO:  
  383.          stereo = FALSE;
  384.          break;
  385.       case OPT_STEREO:  
  386.          stereo = TRUE;
  387.          break;
  388.       case OPT_OVERSAMPLE:  
  389.          oversample = optvalue(1);
  390.          break;
  391.       case OPT_FREQUENCY:
  392.          ask_freq = optvalue(0) * 1000;
  393.          break;
  394.       case OPT_TRANSPOSE:
  395.          transpose = optvalue(0);
  396.          break;
  397.       case OPT_PICKY:
  398.          set_pref_scalar(PREF_TOLERATE, 0);
  399.          break;
  400.       case OPT_TOLERANT:
  401.          set_pref_scalar(PREF_TOLERATE, 2);
  402.          break;
  403.       case OPT_MIX:     /* % of channel mix. 
  404.                          * 0->full stereo, 100->mono */
  405.          set_mix(optvalue(30));
  406.          break;
  407.       case OPT_START:
  408.          start = optvalue(0);
  409.          break;
  410.       case OPT_HELP:
  411.          print_usage();
  412.          end_all(0);
  413.          /* NOTREACHED */
  414.       case OPT_VERBOSE:
  415.          set_pref_scalar(PREF_DUMP, TRUE);
  416.             break;
  417. #ifdef VOLUME_CONTROL
  418.         case OPT_VOLUME:
  419.             volume = optvalue(-20);
  420.             break;
  421.         case OPT_SPEAKER:
  422.             use_speaker = 1;
  423.             break;
  424. #endif
  425.          }
  426.    }
  427.  
  428.  
  429.  
  430. /* song = load_song(filename):
  431.  * syntactic sugar around read_song
  432.  *    - display the file name after stripping the path
  433.  * - find the actual file
  434.  * - read the song trying several formats
  435.  * - handle errors gracefully
  436.  */
  437. LOCAL struct song *load_song(name)
  438. char *name;
  439.    {
  440.    struct song *song;
  441.    char *buffer;
  442.     struct exfile *file;
  443.    int i, j;
  444.    
  445.         /* display the file name */
  446.    i = strlen(name);
  447.    
  448.    for (j = i; j > 0; j--)
  449.       if (name[j] == '/' || name[j] == '\\')
  450.          {
  451.          j++;
  452.          break;
  453.          }
  454.    
  455.    buffer = malloc( i - j + 5);
  456.    if (buffer)
  457.       {
  458.       sprintf(buffer, "%s...", name + j);
  459.       status(buffer);
  460.       }
  461.  
  462.         /* read the song */
  463.     file = open_file(name, "r", getenv("MODPATH"));
  464.     if (file)
  465.         {
  466.         switch(get_pref_scalar(PREF_TYPE))
  467.             {
  468.         case BOTH:
  469.             song = read_song(file, NEW);
  470.             if (song)
  471.                 break;
  472.             else
  473.                 rewind_file(file);
  474.             /* FALLTHRU */
  475.         case OLD:
  476.             song = read_song(file, OLD);
  477.             break;
  478.             /* this is explicitly flagged as a new module,
  479.              * so we don't need to look for a signature.
  480.              */
  481.         case NEW:
  482.             song = read_song(file, NEW_NO_CHECK);
  483.             break;
  484.         default:
  485.             song = NULL;
  486.             }
  487.         close_file(file);
  488.         }
  489.     else
  490.         song = NULL;
  491.  
  492.         /* remove the displayed file name */
  493.     if (buffer)
  494.         {
  495.         status(0);
  496.         free(buffer);
  497.         }
  498.  
  499.     return song;
  500.    }
  501.  
  502.  
  503.  
  504. /* initialize all options to default values */
  505. LOCAL void set_default_prefs()
  506.     {
  507.     char *s;
  508.  
  509.    start = 0;
  510.    set_pref_scalar(PREF_IMASK, 0);
  511.    set_pref_scalar(PREF_BCDVOL, 0);
  512.    set_pref_scalar(PREF_DUMP, FALSE);
  513.    set_pref_scalar(PREF_SHOW, FALSE);
  514. #ifdef COLOR_IS_DEFAULT
  515.    set_pref_scalar(PREF_COLOR, TRUE);
  516. #else
  517.    set_pref_scalar(PREF_COLOR, FALSE);
  518. #endif
  519.    set_pref_scalar(PREF_SYNC, FALSE);
  520.    set_pref_scalar(PREF_TYPE, BOTH);
  521.    set_pref_scalar(PREF_REPEATS, 1);
  522.    set_pref_scalar(PREF_SPEED, 50);
  523.    set_pref_scalar(PREF_TOLERATE, 1);
  524.     set_pref_scalar(PREF_SPEEDMODE, NORMAL_SPEEDMODE);
  525.  
  526.     s = getenv("TERM");
  527.     if (strncmp(s, "xterm", 5) == 0 || strncmp(s, "kterm", 5) == 0 
  528.         || strncmp(s, "cxterm", 6) == 0)
  529.         set_pref_scalar(PREF_XTERM, TRUE);
  530.     else
  531.         set_pref_scalar(PREF_XTERM, FALSE);
  532.    ask_freq = read_env("FREQUENCY", 0);
  533.    oversample = read_env("OVERSAMPLE", 1);
  534.    transpose = read_env("TRANSPOSE", 0);
  535.    stereo = !getenv("MONO");
  536.    set_mix(30);
  537.     }
  538.  
  539.  
  540. LOCAL void adjust_song(s, m)
  541. struct song *s;
  542. unsigned long m;
  543.     {
  544.     int i, j ;
  545.  
  546.     for (i = 1; i <= s->ninstr; i++)
  547.         if ( (1 << i) & ~m)
  548.             {
  549.             for (j = 0; j <= MAX_VOLUME; j++)
  550.                 s->samples[i]->volume_lookup[j] *= 2;
  551.             }
  552.     s->side_width++;
  553.     }
  554.  
  555.  
  556. int main(argc, argv)
  557. int argc;
  558. char **argv;
  559.    {
  560.    struct song *song;
  561.    int *is_song;
  562.    int i;
  563.  
  564.    struct tag *result;
  565.  
  566.     EXPAND_WILDCARDS(argc,argv);
  567.  
  568.    is_song = (int *)malloc(sizeof(int) * argc);
  569.    if (!is_song)
  570.       end_all("No memory left");
  571.  
  572.    for (i = 0; i < argc; i++)
  573.       is_song[i] = FALSE;        /* For termination */
  574.  
  575.     set_default_prefs();
  576.    if (argc == 1)
  577.       {
  578.       print_usage();
  579.       end_all(0);
  580.       }
  581.  
  582.  
  583.  
  584. looping:
  585.    for (optind = 1; optind < argc; optind++)
  586.       {
  587.       parse_options(argc, argv);
  588.       if (optind >= argc)
  589.          end_all(0);
  590.          
  591.    
  592.       song = load_song(argv[optind]);   
  593.       if (song)
  594.          is_song[optind] = TRUE;
  595.       else
  596.          {
  597.          puts("not a song");
  598.          is_song[optind] = FALSE;
  599.          continue;
  600.          }
  601. play_on:
  602.       if (get_pref_scalar(PREF_DUMP))
  603.          dump_song(song); 
  604.         if (half_mask)
  605.             adjust_song(song, half_mask);
  606.       transpose_song(song, transpose);
  607.       setup_audio(ask_freq, stereo, oversample);
  608.       result = play_song(song, start);
  609.       release_song(song);
  610.       status(0);
  611.       while (result = get_tag(result))
  612.          {
  613.          switch (result->type)
  614.             {
  615.          case PLAY_PREVIOUS_SONG:
  616.             optind--;
  617.             while ((optind > 0) && !is_song[optind])
  618.                optind--;
  619.             if (optind == 0)
  620.                     {
  621.                     if (loop)
  622.                         optind = argc - 1;
  623.                     else
  624.                         end_all(0);
  625.                     }
  626.                 song = load_song(argv[optind]);
  627.                 goto play_on;
  628.             /* NOTREACHED */
  629.          case PLAY_LOAD_SONG:
  630.             song = load_song(result->data.pointer);
  631.             free(result->data.pointer);
  632.             if (song)
  633.                goto play_on;
  634.          default:
  635.             break;
  636.             }
  637.          result++;
  638.          }
  639.             
  640.       }
  641.     if (loop)
  642.         goto looping;
  643.    end_all(0);
  644.    /* NOTREACHED */
  645.    }
  646.  
  647.  
  648.